💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    로딩 중이에요... 🐣

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    01 이상치 탐지 | ✅ 저자: 이유정(박사)

    이상치(Outlier)란? 다른 데이터들과 너무 동떨어진 값을 말해요. 예:

    • 평균 나이가 20~70살인데 200살이 있다면? → 이상치!
    • 월급이 대부분 200만~500만인데 1억 원이 있다면? → 이상치!

    이런 값이 있으면 분석 결과나 머신러닝 예측이 엉뚱하게 나올 수 있어요.


    이런 이상치가 왜 생기는가? 입력 실수 나이: 28살 입력하려다 280살 입력 측정 오류 체중 센서가 고장 나서 -15kg 표시 진짜 특이한 사례 일반 직원 연봉은 3천만 원인데, CEO 연봉 5억 단위 착오 월급 500인데 만원 → 원을 잘못 처리해서 5,000,000


    왜 이상치가 문제일까?

    • 평균 계산을 왜곡시켜요.
    • 머신러닝 모델이 이상치에 끌려가서 엉뚱하게 학습해요.
    • 시각화할 때 데이터 범위가 너무 커져 트렌드가 안 보일 수도 있어요.

    이상치를 찾는 대표적인 방법 2가지

    1. IQR 방법 (사분위수 기반) 박스 플롯(Boxplot)에 쓰이는 방식이에요.

    핵심 개념: Q1 : 1사분위수 (25% 지점 값) Q3 : 3사분위수 (75% 지점 값) IQR : Q3 - Q1, 중간 50% 범위

    이상치 기준: Q1 - 1.5×IQR 보다 작거나,
    Q3 + 1.5×IQR 보다 큰 값

    df = pd.read_csv("csv_files/combined_customers.csv")
    
    # Q1, Q3 계산
    Q1 = df['age'].quantile(0.25)
    Q3 = df['age'].quantile(0.75)
    IQR = Q3 - Q1
    
    # 이상치 조건
    outliers = df[(df['age'] < Q1 - 1.5 * IQR) | (df['age'] > Q3 + 1.5 * IQR)]
    # 나이가 (1사분위수보다 1.5 * IQR만큼 작거나)  또는  
    # 나이가 (3사분위수보다 1.5 * IQR만큼 큰)  
    # → 그런 사람은 이상치로 간주한다
    
    
    # 박스 플롯 시각화
    import seaborn as sns
    import matplotlib.pyplot as plt
    sns.boxplot(x=df['age'])
    plt.show()
    

    박스 플롯에서 동그란 점으로 표시되는 것들이 이상치입니다.

    • Q1 - 1.5 * IQR: 너무 작은 값 (이 범위 아래는 이상치)
    • Q3 + 1.5 * IQR: 너무 큰 값 (이 범위 위는 이상치)

    Q1 = df['age'].quantile(0.25)

    나이(age) 데이터를 작은 값부터 큰 값까지 정렬했을 때, 아래쪽 25% 지점의 값을 구합니다. 이걸 제1사분위수 (Q1) 라고 합니다. 예: 나이 순서대로 줄 세웠을 때, 하위 25% 지점의 나이

    Q3 = df['age'].quantile(0.75)

    나이 데이터에서 위쪽 75% 지점의 값, 즉 제3사분위수 (Q3) 를 구해요.
    예: 나이 순서대로 줄 세웠을 때, 상위 25%가 시작되는 나이

    IQR = Q3 - Q1

    IQR (Interquartile Range) 는
    Q1과 Q3 사이의 값의 범위(=중간 50%) 를 의미해요.
    즉, 대부분 사람들이 있는 '정상적인 범위' 라고 보면 돼요.


    1. Z-score 방법 (평균 기반) 평균(Mean) 과 표준편차(Standard Deviation) 를 기준으로 판단하는 방법

    핵심 개념:

    • Z-score는 "이 값이 평균에서 얼마나 떨어졌는지" 를 나타내는 지표예요.
    • 보통 Z-score가 +3 이상 또는 -3 이하이면 "너무 멀리 있다" → 이상치로 간주

    예시:

    • 평균 나이가 40이고, 표준편차가 10이라면
      → 나이 70은 (70 - 40) / 10 = Z-score 3.0 → 이상치!
      → 나이 10도 Z-score -3.0 → 이상치! 표준편차 구하기:
    # 나이데이터
    ages = [20, 22, 24, 26, 28]
    
    # 평균값은 
    (20+22+24+26+28)/5 = 24
    
    # 각 값에서 평균을 뺀 차이 구하기 (편차)
    [20-24, 22-24, 24-24, 26-24, 28-24] → [-4, -2, 0, 2, 4]
    
    # 편차 제곱
    [(-4)^2, (-2)^2, 0^2, 2^2, 4^2] → [16, 4, 0, 4, 16]
    
    # 제곱값 평균
    (16+4+0+4+16​)/5 = 5
    
    # 제곱값 평균의 루트 = 표준편차8 = 2.83
    즉 이 데이터의 표준 편차는 약 2.83입니다.
    

    pandas공식으로 표준편차 구하기:

    import pandas as pd
    
    ages = [20, 22, 24, 26, 28]
    df = pd.DataFrame({'age': ages})
    
    std_population = df['age'].std(ddof=0)
    print("표준편차:", std_population)
    

    Z-Score 기반 이상치 탐지 (정규분포 가정 / 평균과 표준편차 기준)

    import numpy as np
    
    # 평균과 표준편차
    mean_age = np.mean(df['age'])
    std_age = np.std(df['age'])
    
    # Z-score 계산
    df['z_score'] = (df['age'] - mean_age) / std_age
    
    # Z-score가 ±3을 넘으면 이상치
    outliers = df[np.abs(df['z_score']) > 3]
    
    • Z-score는 각 값이 평균에서 얼마나 떨어져 있는지 측정
    • Z-score가 +3 또는 -3을 넘는 데이터는 이상치로 간주
    • 데이터가 정규분포일 때 효과적
    • 사용 예: 센서 데이터, 시험 점수 등

    IQR 기반 이상치 탐지 (중간값 기반 / 사분위수 이용, 비정규 분포에 강함)

    import pandas as pd
    
    df = pd.read_csv("csv_files/combined_customers.csv")
    
    # Q1, Q3 계산
    Q1 = df['age'].quantile(0.25)
    Q3 = df['age'].quantile(0.75)
    IQR = Q3 - Q1
    print(Q1)
    print(Q3)
    print(IQR)
    
    # 이상치 탐지
    outliers = df[(df['age'] < (Q1 - 1.5 * IQR)) | (df['age'] > (Q3 + 1.5 * IQR))]
    print(outliers)
    import seaborn as sns
    import matplotlib.pyplot as plt
    
    # 박스 플롯을 사용한 이상치 시각화
    sns.boxplot(x=df['age'])
    plt.show()
    
    • IQR은 Q3 - Q1: 중간 50% 구간
    • Q1 - 1.5*IQR, Q3 + 1.5*IQR을 벗어난 값 → 이상치
    • 극단값에 덜 민감, 비정규분포 데이터에도 안정적
    • 사용 예: 가격, 소득, 나이 분포 등

    TOP
    preload preload